/**
 *  fileName:call bind apply
 *  time:2022/3/21
 *  todo:$END$
 */

// todo:this
var name = 'windowName'
let name2 = 'windowName2'
function a(){
  let name = 'funName'

  console.log(`this ==> `, this)
  console.log(`this.name ==> `, this.name)
  console.log(`this.name2 ==> `, this.name2)
}
a()

// todo:改变this
var cat = {
  name: '喵喵',
  eatFish: function (param1, param2) {
    console.log('吃鱼')
    console.log('this的指向=>')
    console.log(this)
    console.log(param1, param2)
  }
}

var dog = {
  name: '汪汪',
  eatBone: function (param1, param2) {
    console.log('啃骨头')
    console.log('this的指向=>')
    console.log(this)
    console.log(param1, param2)
  }
}

cat.eatFish.call(dog, 123, 456)
cat.eatFish.apply(dog, [123, 456])
cat.eatFish.bind(dog, 123, 456)()

// todo:改变原理
Function.prototype.myCall = function (context,...arr) {
  console.log(`Object ==> `, Object)
  console.log(`Object('hello') ==> `, Object('hello'))
  console.log(`typeof Object('hello') ==> `, typeof Object('hello'))
  console.log(`Object(123) ==> `, Object(123))

  if(context === null || context === window){
    context = window
  }else {
    context = Object(context)
  }

  const specialProp = Symbol('独立属性')
  context[specialProp] = this
  let result = context[specialProp](...arr)
  delete context[specialProp]
  return result
}
// Function.prototype.myCall = function () {
//   console.log(`arguments ==> `, arguments)
//   console.log(`this ==> `, this) // 谁调用
//
//   let arr = []
//   let obj = {}
//   let target_obj = arguments[0] || window
//
//   target_obj.fn = this
//   // const args = []
//   // for (const argumentsKey in arguments) {
//   //   if(argumentsKey !== '0'){
//   //     args.push(arguments[argumentsKey])
//   //   }
//   // }
//
//   const args = [...arguments] // arguments 是可迭代对象
//   args.shift()
//   target_obj.fn(...args)
//   console.log('****************')
//   // this = arguments[0]
//   // console.log(`this ==> `, this)
// }
//
// console.log('--------------')
cat.eatFish.myCall(dog,123,456)
cat.eatFish.myCall()

// let fn = new Function() // 参数和字符串函数体
// console.log(`fn.constructor.prototype ==> `, fn.constructor.prototype)
// console.log(`fn.constructor.prototype.myCall ==> `, fn.constructor.prototype.myCall)
// console.log(`fn.constructor === Function ==> `, fn.constructor === Function)



// let set = new Set()
// console.log(`typeof set ==> `, typeof set)
// console.log(`set.constructor.toString() ==> `, set.constructor.toString())
// console.log(`Object.prototype.toString.call(set) ==> `, Object.prototype.toString.call(set))
